package com.upstairstechnology.oi.determination.perforce;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.upstairstechnology.oi.determination.AbstractDeterminationStrategyCommand;
import com.upstairstechnology.oi.determination.OutstandingIntegration;
import com.upstairstechnology.oi.determination.OutstandingIntegrationFactory;

/**
 * Determine outstanding integrations for the Perforce SCM.
 * 
 * <pre>
 * p4 interchanges -f -t -b codeline1-to-codeline2
 * Change 1 on 2008/12/21 11:35:33 by jjensen@inter5kh2xb1 'add 2 files '
 * //depot/codeline1/file1.txt#1 add
 * //depot/codeline1/file2.txt#1 add
 * </pre>
 * 
 * @author Jeff Jensen
 */
public class DeterminationStrategyPerforce extends
        AbstractDeterminationStrategyCommand {
    /** Logger instance. */
    private static final Logger LOGGER =
            LoggerFactory.getLogger(DeterminationStrategyPerforce.class);

    /** Constant for element location in line. */
    public static final int CHANGENUM = 1;
    /** Constant for element location in line. */
    public static final int DATE = 3;
    /** Constant for element location in line. */
    public static final int TIME = 4;
    /** Constant for element location in line. */
    public static final int USERIDCLIENT = 6;
    /** Constant for element location in line. */
    public static final int COMMENT_START = 7;

    /** Constant for element location in parsing userid@client. */
    public static final int USERID = 0;
    /** Constant for element location in parsing userid@client. */
    public static final int CLIENT = 1;

    /** Constant for element location in parsing file information. */
    public static final int FILENAME = 1;
    /** Constant for element location in parsing file information. */
    public static final int SCMACTION = 2;

    /** Date formatter for Perforce format. */
    private final transient DateFormat dateFormat =
            new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.getDefault());

    /**
     * {@inheritDoc}
     */
    @Override
    protected void processChangeLine(String lineStd, OutstandingIntegration oi) {
        String[] lineArray = lineStd.split(" ");
        String change = lineArray[CHANGENUM];
        Date timestamp = parseDateTime(lineArray);
        String useridclient = lineArray[USERIDCLIENT];
        String comment = parseComment(lineArray);

        String[] useridclientArray = useridclient.split("@");
        String userId = useridclientArray[USERID];
        String client = useridclientArray[CLIENT];

        oi.setChangeNum(change);
        oi.setTimestamp(timestamp);
        oi.setUserId(userId);
        oi.setClient(client);
        oi.setComment(comment);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void processFileLine(String lineStd, OutstandingIntegration oi) {
        String[] lineArray = lineStd.split(" ");
        String fileName = lineArray[FILENAME];
        String scmAction = lineArray[SCMACTION];

        OutstandingIntegration.File file =
                OutstandingIntegrationFactory.newFile();
        file.setName(fileName);
        file.setAction(scmAction);

        oi.getFiles().add(file);
    }

    /**
     * Parse the commit comment from the line.
     * 
     * @param lineArray
     *            Line to pull date and time from.
     * @return The parsed comment.
     */
    protected String parseComment(String[] lineArray) {
        StringBuilder sbComment = new StringBuilder();

        for (int i = COMMENT_START; i < lineArray.length; i++) {
            String element = lineArray[i];
            sbComment.append(element);
            sbComment.append(' ');
        }

        return sbComment.toString();
    }

    /**
     * Parse the date and time from the line.
     * 
     * @param lineArray
     *            Line to pull date and time from.
     * @return The parsed date/time; null if ParseException.
     */
    protected Date parseDateTime(String[] lineArray) {
        String date = lineArray[DATE];
        String time = lineArray[TIME];
        String dateTime = date + ' ' + time;
        Date timestamp = null; // NOPMD

        try {
            timestamp = dateFormat.parse(dateTime);
        } catch (ParseException e) {
            // TODO implement me
            LOGGER.error("Error parsing change date/time: ", e);
        }

        return timestamp;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }
}
